import 'dart:io';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:shelf_static/shelf_static.dart';
import 'package:shelf_gzip/shelf_gzip.dart';
import 'package:xsdk_flutter/xsdk/operation/x_constant_temp.dart';
import 'package:xsdk_flutter/xsdk/utils/webserver/support/x_demo_restful_api_router_get_photo.dart';
import 'package:xsdk_flutter/xsdk/utils/webserver/support/x_demo_restful_api_router_system.dart';
import 'package:xsdk_flutter/xsdk/utils/webserver/support/x_demo_restful_api_router_upload.dart';
import 'package:xsdk_flutter/xsdk/utils/webserver/support/x_restful_api_router.dart';
import 'package:xsdk_flutter/xsdk/utils/webserver/support/x_utils_middleware.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_date.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_log.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_response.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_string.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_wifi.dart';


/*
后台服务器 web server
https://pub-web.flutter-io.cn/packages/shelf
https://pub-web.flutter-io.cn/packages/shelf_router
https://pub-web.flutter-io.cn/packages/shelf_multipart
https://pub-web.flutter-io.cn/packages/shelf_proxy/install

import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:shelf_static/shelf_static.dart';

dependencies:
  shelf: ^1.4.1
  shelf_router: ^1.1.4
  shelf_static: ^1.1.2
  shelf_gzip: ^4.1.0
  shelf_multipart: ^1.0.0
  shelf_helmet: ^2.3.0
  shelf_proxy: ^1.0.4


其他:
https://pub-web.flutter-io.cn/packages/shelf_web_socket
https://pub-web.flutter-io.cn/packages/shelf_swagger_ui
https://pub-web.flutter-io.cn/packages/shelf_modular
https://pub-web.flutter-io.cn/packages/shelf_letsencrypt
https://pub-web.flutter-io.cn/packages/shelf_enforces_ssl

支持启动多个不同端口服务
注意: request.headers中,需设置Content-Type='application/json' 和 Content-Length的值,这样request.readAsString()才能读出

 */
class XWebServer{
  HttpServer? _httpServer;

  /*
  1.启动
  外界使用对应的局域网ip访问对应api: http://192.168.1.254:8080/test
  本机调自己: http://127.0.0.1:8080/test 或 http://0.0.0.0:8080/test

  customPostRequestRouterMap={};
  customPostRequestRouterMap['/api/getPhoto']=(Request request){
      //...
    };
   */
  void start(
      {
        int port=8080,
        String? staticHandlerFileName,//静态文件名 'index.html' 如果为空,则显示文件夹列表,类似ftp
        List<XRESTFulApiRouter>? customGroupRouterList, //自定义路由组
        Map<String,Function>? customPostRequestRouterMap,//自定义post请求路由
        Map<String,Function>? customGetRequestRouterMap,//自定义get请求路由
      }
      ) async{

    if(port<1024){
      port=8080;
    }

    //静态文件路径(不包括文件名),支持内部图片处理服务,通过ip直接访问: http://192.168.1.254:8080
    //XFileUtils.init();已在app中初始化
    XTempData.localWifiIP= await XWifiUtils.getWifiIP();
    XLogUtils.printLog('---localWifiIP=${XTempData.localWifiIP}');
    String staticHandlerFilePath=XTempData.appDocumentsDirectoryPath;

    //路由
    Router router = Router();
    //如果添加了静态文件服务,此路径则被静态文件服务替代
    if(XStringUtils.isEmpty(staticHandlerFilePath)){
      router.get('/', (Request request) {
        return Response.ok('hello world');
      });
    }

    router.get('/test', (Request request) {
      return Response.ok('test');
    });
    router.get('/test/', (Request request) {
      return Response.ok('hello test');
    });
    router.get('/test/<userId>', (Request request, String userId) {
      return Response.ok('test $userId');
    });
    router.get('/test/u=<userId>', (Request request, String userId) {
      return Response.ok('test u=$userId');
    });
    router.post('/getSystemDate', (Request request) {
      String response=XResponseUtils.responseBodyJson(code: '200', message: 'ok',data: XDateUtils.getCurrentTime_String());
      return Response.ok(response,headers: XResponseUtils.responseHeaders());
    });
    //自定义post请求路由
    if(customPostRequestRouterMap!=null && customPostRequestRouterMap.isNotEmpty){
      customPostRequestRouterMap.forEach( (key, value){
        router.post(key, value);
      } );
    }
    //自定义get请求路由
    if(customGetRequestRouterMap!=null && customGetRequestRouterMap.isNotEmpty){
      customGetRequestRouterMap.forEach( (key, value){
        router.get(key, value);
      } );
    }

    //demo,具有相同url前缀的一组api
    XDemoRESTFulApiRouter_upload routerUpload=XDemoRESTFulApiRouter_upload();//手动定义路由
    XDemoRESTFulApiRouter_system routerSystem=XDemoRESTFulApiRouter_system();//命令自动生成路由
    //图片本地缓存和加载处理
    XDemoRESTFulApiRouter_Photo routerPhoto=XDemoRESTFulApiRouter_Photo(port: port);
    //
    router.mount(routerUpload.urlPrefixPath, routerUpload.router.call);
    router.mount(routerSystem.urlPrefixPath, routerSystem.router.call);
    router.mount(routerPhoto.urlPrefixPath, routerPhoto.router.call);
    //自定义路由组
    if(customGroupRouterList!=null && customGroupRouterList.isNotEmpty){
      for(XRESTFulApiRouter xrestFulApiRouter in customGroupRouterList){
        router.mount(xrestFulApiRouter.urlPrefixPath, xrestFulApiRouter.router.call);
      }
    }

    // You can catch all verbs and use a URL-parameter with a regular expression
    // that matches everything to catch app.
    router.all('/<ignored|.*>', (Request request) {
      //return Response.notFound('XRESTFulApi not found');
      String response=XResponseUtils.responseBodyJson(code: '404', message: 'not found');
      return Response.ok(response,headers: XResponseUtils.responseHeaders());
    });

    XLogUtils.printLog('---XTempData.appDocumentsDirectoryPath=${XTempData.appDocumentsDirectoryPath}');

    //静态文件服务, 访问: http://192.168.1.254:8080
    Handler? staticHandler;
    if(!XStringUtils.isEmpty(staticHandlerFilePath)){
      XLogUtils.printLog('---staticHandlerFilePath=$staticHandlerFilePath');
      staticHandler = createStaticHandler(
        staticHandlerFilePath,//XTempData.appDocumentsDirectoryPath  'example/files',
        defaultDocument: staticHandlerFileName,//'index.html'
        listDirectories: XStringUtils.isEmpty(staticHandlerFileName)?true:false,
      );
    }

    /*
    整合到一个服务中:静态文件服务,websocket服务,路由服务等
    See https://pub.dev/documentation/shelf/latest/shelf/Cascade-class.html
    var cascadeHandler = new Cascade()
     .add(webSocketHandler)
     .add(staticFileHandler)
     .add(application)
     .handler;
     */
    Cascade cascade = Cascade();
    if(staticHandler!=null){
      //添加静态文件服务(注意:这里cascade需要每次重新赋值)
      cascade=cascade.add(staticHandler);
    }
    //添加路由服务(注意:这里cascade需要每次重新赋值)
    cascade=cascade.add(router.call);
    //
    dynamic cascadeHandler = cascade.handler;

    /*
    添加中间件
    https://pub-web.flutter-io.cn/packages/shelf_gzip/install

     */
    var pipelineHandler = const Pipeline()
        //.addMiddleware(helmet()) //自定义中间件
        .addMiddleware(XCustomMiddlewareUtils.getCustomMiddleware()) //自定义中间件
        .addMiddleware(gzipMiddleware) //压缩中间件
        .addHandler(cascadeHandler);

    //启动服务
    serve(
        pipelineHandler,//router,
        InternetAddress.anyIPv4,//0.0.0.0 外界使用对应的局域网ip访问
        port
    ).then((HttpServer server){
      server.autoCompress=true;
      // 添加跨域头
      server.defaultResponseHeaders.add('Access-Control-Allow-Origin', '*');
      server.defaultResponseHeaders.add('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, HEAD, OPTIONS');
      server.defaultResponseHeaders.add('Access-Control-Allow-Credentials', true);
      //server.defaultResponseHeaders.add('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept');
      server.defaultResponseHeaders.add('Access-Control-Allow-Headers', '*');
      _httpServer=server;
      XLogUtils.printLog('---startWebServer: http://${server.address.host}:${server.port}');
    }).onError((error, stackTrace){
      XLogUtils.printLog('---HttpServer,error=$error, stackTrace=$stackTrace');
    });
  }

  //2.关闭
  void close(){
    _httpServer?.close();
  }

}








